package cn.com.header.zbpk.web.security;

import cn.com.header.core.support.web.JsonViewData;
import cn.com.header.core.support.web.ResultCode;
import cn.com.header.zbpk.account.entity.Role;
import cn.com.header.zbpk.account.entity.User;
import cn.com.header.zbpk.account.service.IRoleService;
import cn.com.header.zbpk.account.service.IUserService;
import cn.com.header.zbpk.account.service.impl.UserServiceImpl;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.LockedException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Map;

/**
 * 登录注销处理器，异步调用触发
 *
 * @author Liangzhongqiu
 * @date 2017-09-04
 * @time 21:09
 */
public class LoginLogoutHandler implements AuthenticationSuccessHandler, AuthenticationFailureHandler, LogoutSuccessHandler {

    protected Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private IUserService iUserService;

    @Autowired
    private IRoleService iRoleService;

    /**
     * 登录失败
     * <pre>
     *     {"returnCode":"SUCCESS","message":"{{message}}"}
     * </pre>
     *
     * @param request   请求
     * @param response  响应
     * @param exception 授权异常
     */
    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
        String message = "对不起，您的账号/密码错误，请检查后再登陆！";
        if (exception instanceof UsernameNotFoundException) {
            message = "对不起，您的账号错误，请检查后再登陆！";
        } else if (exception instanceof BadCredentialsException) {
            message = "对不起，您的密码错误，请检查后再登陆！";
        } else if (exception instanceof LockedException) {
            message = "对不起，您的账号已被锁定！";
        }else if(exception instanceof DisabledException){
            message = "对不起，您的账号已被禁用！";
        }
        logger.warn(message);
        new JsonViewData(ResultCode.FAIL, message).write(response);
    }

    /**
     * 登录成功
     * {"returnCode":"SUCCESS","message":"登录成功。"}
     *
     * @param request        请求
     * @param response       响应
     * @param authentication 身份凭证
     */
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        UserServiceImpl.SecurityUser securityUser = (UserServiceImpl.SecurityUser) authentication.getPrincipal();
        Long userId = securityUser.getId();
        User user = iUserService.loadByPK(userId, Sets.newHashSet("id", "name", "password_updated")).get();
        Map<String, Object> userMap = Maps.newHashMapWithExpectedSize(6);
        userMap.put("id", user.getId());
        userMap.put("name", user.getName());
        userMap.put("passwordUpdated", user.getPasswordUpdated());
        List<Role> roleList = iRoleService.queryRoleByUserId(userId);
        userMap.put("roleList", roleList);
        Map<String, Object> data = Maps.newLinkedHashMapWithExpectedSize(2);
        data.put("user", userMap);
        request.getSession().setAttribute("sessionUser",securityUser);
        // TODO 用户权限
        new JsonViewData(data).write(response);
    }

    /**
     * 成功注销
     * <pre>
     *     {"returnCode":"SUCCESS","message":"成功退出。"}
     * </pre>
     *
     * @param request        请求
     * @param response       响应
     * @param authentication 身份凭证
     */
    @Override
    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        new JsonViewData(ResultCode.SUCCESS, "成功退出。").write(response);
    }

}
